import os
from time import gmtime, strftime
from django.db import models
from django.contrib.contenttypes import generic 
from django.contrib.auth.models import User
from django.core.files import File as DjangoFile

from jobs.models import Job   

from cache import model_property_cache

from assets.signals import asset_changed

import logging
LOG = logging.getLogger("files.models")


class FileManager(models.Manager):
  def get_by_natural_key(self, hash):
    return self.get(hash=hash)
    
  def get_or_create_from(self, aFileReference):
    hash = aFileReference.hash if not aFileReference.brokenReference else aFileReference.fileNameHash
    try:
      f = File.objects.get(hash=hash)
      created = False
    except File.DoesNotExist:
      if not hasattr(aFileReference, 'user'):
        user = User.objects.all()[0] #TODO
      else:
        user, cu = User.objects.get_or_create(username=aFileReference.user)
      
      file = open(aFileReference.fileName)
      djangofile = DjangoFile(file)
      base = os.path.basename(aFileReference.fileName)
      f = File(file_name=base, author=user, hash=hash)
      f.location.save(base, djangofile)
      f.save()
      created = True

    file_path, cp = FilePath.objects.get_or_create(file=f, file_path=aFileReference.fileName)
    if cp:
      paths = FilePath.objects.filter(file_path=aFileReference.fileName).exclude(file=f)
      if len(paths):
        f.ancestor = paths[0].file.latest
        f.save()

    return f, created


def File_location(instance, filename):
  u = instance.author.username if instance.author else 'anonymous'
  return strftime('store/'+u+'/%Y/%m/%d/'+filename, gmtime())
   

class File(models.Model):
  hash = models.CharField(max_length=40, unique=True)  
  ancestor = models.ForeignKey('self', blank=True, null=True, related_name='descendants')
  file_name = models.CharField(max_length=256)
  
  location = models.FileField(upload_to=File_location, max_length=4096)
  
  stamp = models.DateTimeField(auto_now=True, auto_now_add=True, db_index=True)
  
  author = models.ForeignKey(User)
  
  jobs = generic.GenericRelation(Job)
  
  class Meta:
    db_table = 'Files'
    verbose_name_plural = "Files"
    #unique_together = (("repository", "parent", "fileName"),)
  
  @property
  @model_property_cache
  def version(self):
    return (self.ancestor.version if self.ancestor else 0)+1
  
  @property
  def is_latest(self):
    return self.descendants.count() == 0
    
  @property
  @model_property_cache
  def latest(self):
    return self.descendant if self.descendant else self
  
  @property
  @model_property_cache
  def descendant(self):
    return self.descendants.all()[0] if len(self.descendants.all()) else None
      
  objects = FileManager()
  def natural_key(self):
    return (self.hash)
    
  @models.permalink
  def get_absolute_url(self):
    return ('webgui.views.file', [str(self.id)])
  
  @property
  def display_name(self):  
    return 'File: %s'%(self.file_name)
    
  def __unicode__(self):
    return '[%s] %s - %s'%(str(self.id), self.hash, self.file_name)

  def analyze(self):
    from damn import AnalyzerInstance, TranscoderInstance
    from assets.models import Asset
    LOG.info("Started analyzing file %s (%s)...", self.pk, self.location.path)
    fileRef = AnalyzerInstance().AnalyzeFile(self.location.path)
    for asset in fileRef.assets:
      a, c = Asset.objects.get_or_create_from(asset)
      asset._id = a.id
      TranscoderInstance().delete_asset_cache(asset)
      LOG.info("Bumping versions.\n")
      for version in a.version_set.all():
        version.version = version.version+1
        version.save()
      asset_changed.send(sender=a)


class FilePath(models.Model):
  file = models.ForeignKey(File)  
  file_path = models.CharField(max_length=255)
  
  class Meta:
    db_table = 'FilePaths'
    verbose_name_plural = "File paths"
    unique_together = (("file", "file_path"),)
    
  def __unicode__(self):
    return '%s - %s'%(self.file.file_name, self.file_path)
